#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         UserProviderService.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  Defines an abstract service that is used to provide
#               the KnowledgeEngine internal security model with
#               'User' instances.
#
#               This service provides a layer of protection over
#               User management.  For example, implementations of this
#               service may include; Zope ACL User Folders, Plone
#               User Folders, MySQL or LDAP implementations.
#
#               This service does not in general provide the ability
#               to create users as this is often implementation
#               dependant.
#
# See Also:     Service, User, Group, GroupProviderService
#####################################################################
#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Service import ServiceInfo, Service
from Products.KnowledgeEngine.User import User
from Products.KnowledgeEngine.Caching import RequestCache

#####################################################################
## Zope Library Imports
# (none)
#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
# (none)
#####################################################################
## UserProviderService Class Definition
class UserProviderServiceInfo(ServiceInfo):
    """
        Defines the the user provider service meta-information
    """
    
    #---------------------------------------------------------------#
    
    def getClassName(self):
        """
            Returns the name of the class for which 
            we are providing information.
        """
        return 'UserProviderService'

    #---------------------------------------------------------------#
    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """
    
        return "KnowledgeEngine: User Provider Service"
        
    #---------------------------------------------------------------#
    def getServiceName(self):
        """
            ABSTRACT: Return the lookup-identity.
            
            This method must be overriden to provide a unique service name
            (this name is used to set the zope id of the service
            when created)
        """
        
        return "knowledgeengine_userproviderservice"
#####################################################################
## UserProviderService Class Definition
class UserProviderService(Service):
    """
        Defines a tool that may be used to manage Knowledge Engine
        users
    """
    #---------------------------------------------------------------#
    #ABSTRACT TRANSIENT: a ServiceInfo implementation instance to provide info about this service
    _SERVICEINFO = UserProviderServiceInfo()
    #---------------------------------------------------------------#
    def __init__(self):
        """
            Constructor for the object
        """
        
        #this is a stateless mix-in
        pass
        
    #---------------------------------------------------------------#
    def getUser(self, userIdentity):
        """
            Returns a Knowledge Engine User instance for the 
            user with the provided identity.
            
            The userIdentity is a unique string that identifies the user
            with for the service implementation.  Typically this is
            the user login name (but is actually implementation dependant)
            
            Returns None if the user is unknown.
            
            RETURN TYPE: User
        """
        
        return None
    #---------------------------------------------------------------#
    def getUsers(self, includeAnonymousUser = false):
        """
            Returns a UserIterator over the available Users 
            from the service implementation
            
            RETURN TYPE: [User]
        """
        
        return []
        
    #---------------------------------------------------------------#
    
    def searchUsers(self, searchString):
        """
            Returns a UserIterator over the Users 
            matching a string query against id, email and full name
            
            RETURN TYPE: [User]
        """
        
        return []
        
    #---------------------------------------------------------------#

    def getUserSetFromScope(self, scope, model, user):
        """
            return a set of scope for a user in the cache if it exist
            else get set of scope for the user and cache it

            PARAMETERS:
            scope : List of actor identity eg. ['*','authenticateduser','authenticatedusergroup','authenticateusermanagedgroup']
            model : the Model
            user : User object or a string of userIdentity

            RETURN TYPE: String
       """

        cache = RequestCache("getUserSetFromScope", self.REQUEST)
        # Build a uniqe cache id
        for singleScope in scope:
            singleScope += singleScope
        if type(user) == User:
            authenticatedUserIdentity = user.getIdentity()
        else:
            authenticatedUserIdentity = user

        c_hash = str("getUserSetFromScope"  + singleScope + model.getIdentity() + authenticatedUserIdentity)
        
        if c_hash in cache:
               return cache[c_hash]

        userSet = ""
        for actorIdentity in scope:
            if actorIdentity == 'authenticateduser':
                if len(userSet) > 0:
                    userSet = userSet + ","
                userSet = userSet + ("'%s'" % authenticatedUserIdentity)

            elif actorIdentity == 'authenticatedusergroup' or actorIdentity == 'authenticatedusermanagedgroup':
                #get the group provider service so we can determine the members of the group
                groupProviderService = model.getGroupProviderService()

                #determine the groups from which to derive users
                if actorIdentity == 'authenticatedusergroup':
                    #get the groups to which the user belongs
                    groups = groupProviderService.getGroupsForActor(authenticatedUserIdentity)
                else:
                    #get the groups that the actor is managing
                    groups = groupProviderService.getGroupsManagedByActor(authenticatedUserIdentity)

                #add all of the users in each of the groups to the user set
                for group in groups:
                    for userIdentity in groupProviderService.getUserIdentitiesInGroup(group.getIdentity()):
                        if len(userSet) > 0:
                            userSet = userSet + ","
                        userSet = userSet + ("'%s'" % userIdentity)

            else:
                if len(userSet) > 0:
                    userSet = userSet + ","
                    userSet = userSet + ("'%s'" % actorIdentity)

        cache[c_hash] = userSet
        return userSet

    #---------------------------------------------------------------#    
#####################################################################
## Class Initialisation
# (none)
